package com.xb.xbpm.utils;


import com.alibaba.fastjson.JSONObject;
import com.xb.xbpm.bean.Ips;
import com.xb.xbpm.bean.Newuv;
import com.xb.xbpm.bean.Pv;
import com.xb.xbpm.bean.Uv;
import com.xb.xbpm.mapper.IpsMapper;
import com.xb.xbpm.mapper.NewuvMapper;
import com.xb.xbpm.mapper.PvMapper;
import com.xb.xbpm.mapper.UvMapper;
import com.xb.xbpm.service.RateCalculation;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.ActionFuture;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequest;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
import org.elasticsearch.action.admin.indices.stats.IndicesStatsRequest;
import org.elasticsearch.action.admin.indices.stats.IndicesStatsResponse;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequestBuilder;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.BucketOrder;
import org.elasticsearch.search.aggregations.bucket.MultiBucketsAggregation;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval;
import org.elasticsearch.search.aggregations.bucket.histogram.Histogram;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.metrics.cardinality.Cardinality;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 1.字符串 条件用matchQuery  其余用termQuery
 * 2.忽略索引是否存在 setIndicesOptions(IndicesOptions.lenientExpandOpen());
 * 3.聚合排序.order(BucketOrder.count(flag))  //size(10)设置数量
 *
 * @Author gxd
 * @Date： 2018/7/23
 */
@Component
public class EsUtils {

    @Autowired
    private TransportClient transportClient;

    private static TransportClient client;

    @Autowired
    private PvMapper pvMapper;
    @Autowired
    private UvMapper uvMapper;
    @Autowired
    private IpsMapper ipsMapper;
    @Autowired
    private NewuvMapper newuvMapper;

    @PostConstruct
    public void init() {
        client = this.transportClient;
    }

    /**
     * 创建索引
     *
     * @param index
     * @return
     */
    public static boolean createIndex(String index) {
        if (!isIndexExist(index)) {
            //LOGGER.info("Index is not exits!");
        }
        CreateIndexResponse indexresponse = client.admin().indices().prepareCreate(index).execute().actionGet();
        //LOGGER.info("执行建立成功？" + indexresponse.isAcknowledged());

        return indexresponse.isAcknowledged();
    }

    /**
     * 删除索引
     *
     * @param index
     * @return
     */
    public static boolean deleteIndex(String index) {
        if (!isIndexExist(index)) {
            //LOGGER.info("Index is not exits!");
        }
        DeleteIndexResponse dResponse = client.admin().indices().prepareDelete(index).execute().actionGet();
        if (dResponse.isAcknowledged()) {
            //LOGGER.info("delete index " + index + "  successfully!");
        } else {
            //LOGGER.info("Fail to delete index " + index);
        }
        return dResponse.isAcknowledged();
    }

    /**
     * 判断索引是否存在
     *
     * @param index
     * @return
     */
    public static boolean isIndexExist(String index) {
        IndicesExistsResponse inExistsResponse = client.admin().indices().exists(new IndicesExistsRequest(index)).actionGet();
        if (inExistsResponse.isExists()) {
            //LOGGER.info("Index [" + index + "] is exist!");
        } else {
            //LOGGER.info("Index [" + index + "] is not exist!");
        }
        return inExistsResponse.isExists();
    }

    /**
     * 数据添加，正定ID
     *
     * @param jsonObject 要增加的数据
     * @param index      索引，类似数据库
     * @param type       类型，类似表
     * @param id         数据ID
     * @return
     */
    public static String addData(JSONObject jsonObject, String index, String type, String id) {

        IndexResponse response = client.prepareIndex(index, type, id).setSource(jsonObject).get();

        //LOGGER.info("addData response status:{},id:{}", response.status().getStatus(), response.getId());

        return response.getId();
    }

    /**
     * 数据添加
     *
     * @param jsonObject 要增加的数据
     * @param index      索引，类似数据库
     * @param type       类型，类似表
     * @return
     */
    public static String addData(JSONObject jsonObject, String index, String type) {
        return addData(jsonObject, index, type, UUID.randomUUID().toString().replaceAll("-", "").toUpperCase());
    }

    /**
     * 通过ID删除数据
     *
     * @param index 索引，类似数据库
     * @param type  类型，类似表
     * @param id    数据ID
     */
    public static void deleteDataById(String index, String type, String id) {

        DeleteResponse response = client.prepareDelete(index, type, id).execute().actionGet();

        //LOGGER.info("deleteDataById response status:{},id:{}", response.status().getStatus(), response.getId());
    }

    /**
     * 通过ID 更新数据
     *
     * @param jsonObject 要增加的数据
     * @param index      索引，类似数据库
     * @param type       类型，类似表
     * @param id         数据ID
     * @return
     */
    public static void updateDataById(JSONObject jsonObject, String index, String type, String id) {

        UpdateRequest updateRequest = new UpdateRequest();

        updateRequest.index(index).type(type).id(id).doc(jsonObject);

        client.update(updateRequest);

    }

    /**
     * 通过ID获取数据
     *
     * @param index  索引，类似数据库
     * @param type   类型，类似表
     * @param id     数据ID
     * @param fields 需要显示的字段，逗号分隔（缺省为全部字段）
     * @return
     */
    public static Map<String, Object> searchDataById(String index, String type, String id, String fields) {

        GetRequestBuilder getRequestBuilder = client.prepareGet(index, type, id);

        if (StringUtils.isNotEmpty(fields)) {
            getRequestBuilder.setFetchSource(fields.split(","), null);
        }

        GetResponse getResponse =  getRequestBuilder.execute().actionGet();

        return getResponse.getSource();
    }






    /**
     * 使用分词查询
     *
     * @param index    索引名称
     * @param type     类型名称,可传入多个type逗号分隔
     * @param fields   需要显示的字段，逗号分隔（缺省为全部字段）
     * @param matchStr 过滤条件（xxx=111,aaa=222）
     * @return
     */
    public static List<Map<String, Object>> searchListData(String index, String type, String fields, String matchStr) {
        return searchListData(index, type, 0, 0, null, fields, null, false, null, matchStr);
    }

    /**
     * 聚合查询
     *
     */

//    public static List<Map<String, Object>> searchListData(String index,String type,String fields,String id,String mastchStr){
//        GetRequestBuilder getRequestBuilder = client.prepareGet(index, type, id);
//
//        return null;
//    }

    /**
     * 使用分词查询
     *
     * @param index       索引名称
     * @param type        类型名称,可传入多个type逗号分隔
     * @param fields      需要显示的字段，逗号分隔（缺省为全部字段）
     * @param sortField   排序字段
     * @param matchPhrase true 使用，短语精准匹配
     * @param matchStr    过滤条件（xxx=111,aaa=222）
     * @return
     */
    public static List<Map<String, Object>> searchListData(String index, String type, String fields, String sortField, boolean matchPhrase, String matchStr) {
        return searchListData(index, type, 0, 0, null, fields, sortField, matchPhrase, null, matchStr);
    }


    /**
     * 使用分词查询
     *
     * @param index          索引名称
     * @param type           类型名称,可传入多个type逗号分隔
     * @param size           文档大小限制
     * @param fields         需要显示的字段，逗号分隔（缺省为全部字段）
     * @param sortField      排序字段
     * @param matchPhrase    true 使用，短语精准匹配
     * @param highlightField 高亮字段
     * @param matchStr       过滤条件（xxx=111,aaa=222）
     * @return
     */
    public static List<Map<String, Object>> searchListData(String index, String type, Integer size, String fields, String sortField, boolean matchPhrase, String highlightField, String matchStr) {
        return searchListData(index, type, 0, 0, size, fields, sortField, matchPhrase, highlightField, matchStr);
    }



    /**
     * 使用分词查询
     *
     * @param index          索引名称
     * @param type           类型名称,可传入多个type逗号分隔
     * @param startTime      开始时间
     * @param endTime        结束时间
     * @param size           文档大小限制
     * @param fields         需要显示的字段，逗号分隔（缺省为全部字段）
     * @param sortField      排序字段
     * @param matchPhrase    true 使用，短语精准匹配
     * @param highlightField 高亮字段
     * @param matchStr       过滤条件（xxx=111,aaa=222）
     * @return
     */
    public static List<Map<String, Object>> searchListData(String index, String type, long startTime, long endTime, Integer size, String fields, String sortField, boolean matchPhrase, String highlightField, String matchStr) {

        SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index);
        if (StringUtils.isNotEmpty(type)) {
            searchRequestBuilder.setTypes(type.split(","));
        }
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

        if (startTime > 0 && endTime > 0) {
            boolQuery.must(QueryBuilders.rangeQuery("processTime")
                    .format("epoch_millis")
                    .from(startTime)
                    .to(endTime)
                    .includeLower(true)
                    .includeUpper(true));
        }

        //搜索的的字段
        if (StringUtils.isNotEmpty(matchStr)) {
            for (String s : matchStr.split(",")) {
                String[] ss = s.split("=");
                if (ss.length > 1) {
                    if (matchPhrase == Boolean.TRUE) {
                        boolQuery.must(QueryBuilders.matchPhraseQuery(s.split("=")[0], s.split("=")[1]));
                    } else {
                        boolQuery.must(QueryBuilders.matchQuery(s.split("=")[0], s.split("=")[1]));
                    }
                }

            }
        }

        // 高亮（xxx=111,aaa=222）
        if (StringUtils.isNotEmpty(highlightField)) {
            HighlightBuilder highlightBuilder = new HighlightBuilder();

            //highlightBuilder.preTags("<span style='color:red' >");//设置前缀
            //highlightBuilder.postTags("</span>");//设置后缀

            // 设置高亮字段
            highlightBuilder.field(highlightField);
            searchRequestBuilder.highlighter(highlightBuilder);
        }


        searchRequestBuilder.setQuery(boolQuery);

        if (StringUtils.isNotEmpty(fields)) {
            searchRequestBuilder.setFetchSource(fields.split(","), null);
        }
        searchRequestBuilder.setFetchSource(true);

        if (StringUtils.isNotEmpty(sortField)) {
            searchRequestBuilder.addSort(sortField, SortOrder.DESC);
        }

        if (size != null && size > 0) {
            searchRequestBuilder.setSize(size);
        }

        //打印的内容 可以在 Elasticsearch head 和 Kibana  上执行查询
        //LOGGER.info("\n{}", searchRequestBuilder);

        SearchResponse searchResponse = searchRequestBuilder.execute().actionGet();

        long totalHits = searchResponse.getHits().totalHits;
        long length = searchResponse.getHits().getHits().length;

        //LOGGER.info("共查询到[{}]条数据,处理数据条数[{}]", totalHits, length);

        if (searchResponse.status().getStatus() == 200) {
            // 解析对象
            return setSearchResponse(searchResponse, highlightField);
        }

        return null;

    }

    /**
     * 使用分词查询,并分页
     *
     * @param index          索引名称
     * @param type           类型名称,可传入多个type逗号分隔
     * @param currentPage    当前页
     * @param pageSize       每页显示条数
     * @param startTime      开始时间
     * @param endTime        结束时间
     * @param fields         需要显示的字段，逗号分隔（缺省为全部字段）
     * @param sortField      排序字段
     * @param matchPhrase    true 使用，短语精准匹配
     * @param highlightField 高亮字段
     * @param matchStr       过滤条件（xxx=111,aaa=222）
     * @return
     */
    public static EsPage searchDataPage(String index, String type, int currentPage, int pageSize, long startTime, long endTime, String fields, String sortField, boolean matchPhrase, String highlightField, String matchStr) {
        SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index);
        if (StringUtils.isNotEmpty(type)) {
            searchRequestBuilder.setTypes(type.split(","));
        }
        searchRequestBuilder.setSearchType(SearchType.QUERY_THEN_FETCH);

        // 需要显示的字段，逗号分隔（缺省为全部字段）
        if (StringUtils.isNotEmpty(fields)) {
            searchRequestBuilder.setFetchSource(fields.split(","), null);
        }

        //排序字段
        if (StringUtils.isNotEmpty(sortField)) {
            searchRequestBuilder.addSort(sortField, SortOrder.DESC);
        }

        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

        if (startTime > 0 && endTime > 0) {
            boolQuery.must(QueryBuilders.rangeQuery("processTime")
                    .format("epoch_millis")
                    .from(startTime)
                    .to(endTime)
                    .includeLower(true)
                    .includeUpper(true));
        }

        // 查询字段
        if (StringUtils.isNotEmpty(matchStr)) {
            for (String s : matchStr.split(",")) {
                String[] ss = s.split("=");
                if (matchPhrase == Boolean.TRUE) {
                    boolQuery.must(QueryBuilders.matchPhraseQuery(s.split("=")[0], s.split("=")[1]));
                } else {
                    boolQuery.must(QueryBuilders.matchQuery(s.split("=")[0], s.split("=")[1]));
                }
            }
        }

        // 高亮（xxx=111,aaa=222）
        if (StringUtils.isNotEmpty(highlightField)) {
            HighlightBuilder highlightBuilder = new HighlightBuilder();

            //highlightBuilder.preTags("<span style='color:red' >");//设置前缀
            //highlightBuilder.postTags("</span>");//设置后缀

            // 设置高亮字段
            highlightBuilder.field(highlightField);
            searchRequestBuilder.highlighter(highlightBuilder);
        }

        searchRequestBuilder.setQuery(QueryBuilders.matchAllQuery());
        searchRequestBuilder.setQuery(boolQuery);

        // 分页应用
        searchRequestBuilder.setFrom(currentPage).setSize(pageSize);

        // 设置是否按查询匹配度排序
        searchRequestBuilder.setExplain(true);

        //打印的内容 可以在 Elasticsearch head 和 Kibana  上执行查询
        //LOGGER.info("\n{}", searchRequestBuilder);

        // 执行搜索,返回搜索响应信息
        SearchResponse searchResponse = searchRequestBuilder.execute().actionGet();

        long totalHits = searchResponse.getHits().totalHits;
        long length = searchResponse.getHits().getHits().length;

        //LOGGER.debug("共查询到[{}]条数据,处理数据条数[{}]", totalHits, length);

        if (searchResponse.status().getStatus() == 200) {
            // 解析对象
            List<Map<String, Object>> sourceList = setSearchResponse(searchResponse, highlightField);

            return new EsPage(currentPage, pageSize, (int) totalHits, sourceList);
        }

        return null;

    }

    /**
     * 高亮结果集 特殊处理
     *
     * @param searchResponse
     * @param highlightField
     */
    private static List<Map<String, Object>> setSearchResponse(SearchResponse searchResponse, String highlightField) {
        List<Map<String, Object>> sourceList = new ArrayList<Map<String, Object>>();
        StringBuffer stringBuffer = new StringBuffer();

        for (SearchHit searchHit : searchResponse.getHits().getHits()) {
            //searchHit.getSource().put("id", searchHit.getId());
            searchHit.getSourceAsMap().put("id", searchHit.getId());

            if (StringUtils.isNotEmpty(highlightField)) {

                System.out.println("遍历 高亮结果集，覆盖 正常结果集" + searchHit.getSourceAsMap());
                Text[] text = searchHit.getHighlightFields().get(highlightField).getFragments();

                if (text != null) {
                    for (Text str : text) {
                        stringBuffer.append(str.string());
                    }
                    //遍历 高亮结果集，覆盖 正常结果集
                    searchHit.getSourceAsMap().put(highlightField, stringBuffer.toString());
                }
            }
            sourceList.add(searchHit.getSourceAsMap());
        }

        return sourceList;
    }


    public static List<Map<String,Object>> searchCountData(String index, String type){

        List<Map<String,Object>> resultlist = new ArrayList<Map<String, Object>>();



        //初始化builder
        SearchRequestBuilder searchBuilder=client.prepareSearch(index).setTypes(type);
        AggregationBuilder aggregationBuilder = AggregationBuilders.terms("city_agg").field("city.keyword");

        SearchResponse response = searchBuilder.setQuery(QueryBuilders.matchQuery("title", "统计信息"))
                .addAggregation(aggregationBuilder)
                .setExplain(true).execute().actionGet();

        Terms agg = response.getAggregations().get("city_agg");
        System.out.println(agg.getBuckets());
        for (Terms.Bucket bucket : agg.getBuckets()) {
//            System.out.println(bucket.getKey() + ":" + bucket.getDocCount());
            Map<String,Object> map = new HashMap<>();
            map.put(bucket.getKey().toString(),bucket.getDocCount());
            resultlist.add(map);
        }
        return resultlist;
    }


    public static List<Map<String, Object>> searchDemo(String index, String type){

        List<Map<String,Object>> resultlist = new ArrayList<Map<String, Object>>();



        //初始化builder
        SearchRequestBuilder searchBuilder=client.prepareSearch(index).setTypes(type);
        //AggregationBuilder aggregationBuilder = AggregationBuilders.terms("city_agg").field("city.keyword");
        AggregationBuilder aggregation = AggregationBuilders
                .dateHistogram("agg")
                .field("time")
                .format("yyyy-MM-dd")
                .dateHistogramInterval(DateHistogramInterval.DAY);



        SearchResponse response = searchBuilder.setQuery(QueryBuilders.matchQuery("title", "统计信息"))
                .addAggregation(aggregation)
                .setExplain(true).execute().actionGet();


        Histogram agg=response.getAggregations().get("agg");
        System.out.println(agg.getBuckets());
        for (Histogram.Bucket bucket : agg.getBuckets()) {
//            System.out.println(bucket.getKey() + ":" + bucket.getDocCount());
            Map<String,Object> map = new HashMap<>();
            map.put(bucket.getKey().toString(),bucket.getDocCount());
            resultlist.add(map);
        }
        return resultlist;


    }



    /**查询pv总量信息*/
    public long getTotalCountPv(String index, String siteid) throws Exception {
        //.setIndicesOptions(IndicesOptions.lenientExpandOpen()); 作用:如果索引不存在 忽略，不报错

        SearchRequestBuilder searchBuilder = client.prepareSearch(index.split(",")).setIndicesOptions(IndicesOptions.lenientExpandOpen());
        SearchResponse searchResponse = searchBuilder.setQuery(QueryBuilders.termQuery("siteid", siteid))
                .setSize(0)
                .execute().actionGet();
        long totalHits = searchResponse.getHits().totalHits;
        return totalHits;
    }

    /**查询uv总量信息*/
    public long getTotalCountUv(String index, String siteid) {
        SearchRequestBuilder searchBuilder = client.prepareSearch(index.split(",")).setIndicesOptions(IndicesOptions.lenientExpandOpen());

        //去重uuid
        AggregationBuilder ca= AggregationBuilders.cardinality("distinct_count_uuid").field("uuid.keyword");

        SearchResponse searchResponse = searchBuilder.setQuery(QueryBuilders.termQuery("siteid", siteid))
                .addAggregation(ca)
                .setSize(0)
                .execute().actionGet();

        Cardinality agg=null;
        if(searchResponse.getAggregations()!=null){
            agg= searchResponse.getAggregations().get("distinct_count_uuid");
        }


        long uvcount=0;
        if(agg!=null){
            uvcount=agg.getValue();
        }

        return uvcount;
    }

    /**查询独立ip 总量信息*/
    public long getTotalCountIp(String index, String siteid) {
        SearchRequestBuilder searchBuilder = client.prepareSearch(index.split(",")).setIndicesOptions(IndicesOptions.lenientExpandOpen());
        //去重uuid
        AggregationBuilder ca= AggregationBuilders.cardinality("distinct_count_ip").field("ip.keyword");

        SearchResponse searchResponse = searchBuilder.setQuery(QueryBuilders.termQuery("siteid", siteid))
                .addAggregation(ca)
                .setSize(0)
                .execute().actionGet();

        Cardinality agg=null;
        if(searchResponse.getAggregations()!=null){
            agg= searchResponse.getAggregations().get("distinct_count_ip");
        }
        long ipcount=0;
        if(agg!=null){
            ipcount=agg.getValue();
        }

        return ipcount;
    }

    public  List<Map<String, Object>> getPvByTimeNode(String index, String type,String siteid,int curTime){
        SearchRequestBuilder searchBuilder = client.prepareSearch(index).setIndicesOptions(IndicesOptions.lenientExpandOpen());
        List<Map<String, Object>> list=new ArrayList<Map<String, Object>>();
        for (int i=0;i<=curTime;i++){
            SearchResponse searchResponse = searchBuilder.setQuery(QueryBuilders.boolQuery()
                    .filter(QueryBuilders.termQuery("siteid", siteid))
                    .filter(QueryBuilders.rangeQuery("times").gte(i).lt(i+1)))
                    .setSize(0)
                    .execute().actionGet();
            long totalHits = searchResponse.getHits().totalHits;//0-1 1-2 2-3点
            Map<String,Object> map = new HashMap<>();
            map.put("day",i+":00-"+i+":59");
            map.put("count",totalHits);
            list.add(map);
        }
        return  list;
    }

    public  List<Map<String, Object>> getUvByTimeNode(String index, String type,String siteid,int curTime){
        SearchRequestBuilder searchBuilder = client.prepareSearch(index).setIndicesOptions(IndicesOptions.lenientExpandOpen());
        List<Map<String, Object>> list=new ArrayList<Map<String, Object>>();

        for (int i=0;i<=curTime;i++){
            //去重uuid
            AggregationBuilder ca= AggregationBuilders.cardinality("distinct_uuid"+i).field("uuid.keyword");

            SearchResponse searchResponse= searchBuilder.setQuery(QueryBuilders.boolQuery()
                    .filter(QueryBuilders.termQuery("siteid", siteid))
                    .filter(QueryBuilders.rangeQuery("times").gte(i).lt(i+1)))
                    .addAggregation(ca)
                    .setSize(0)
                    .execute().actionGet();


            Cardinality agg=null;
            if(searchResponse.getAggregations()!=null){
                agg= searchResponse.getAggregations().get("distinct_uuid"+i);
            }
            long uuidcount=0;
            if(agg!=null){
                uuidcount=agg.getValue();//0-1 1-2 2-3点
            }

            Map<String,Object> map = new HashMap<>();
            map.put("day",i+":00-"+i+":59");
            map.put("count",uuidcount);
            list.add(map);
        }
        return  list;
    }

    public  List<Map<String, Object>> getIpByTimeNode(String index, String type,String siteid,int curTime){
        SearchRequestBuilder searchBuilder = client.prepareSearch(index).setIndicesOptions(IndicesOptions.lenientExpandOpen());
        List<Map<String, Object>> list=new ArrayList<Map<String, Object>>();
        for (int i=0;i<=curTime;i++){
            //去重ip
            AggregationBuilder ca= AggregationBuilders.cardinality("distinct_ip"+i).field("ip.keyword");

            SearchResponse searchResponse= searchBuilder.setQuery(QueryBuilders.boolQuery()
                    .filter(QueryBuilders.termQuery("siteid", siteid))
                    .filter(QueryBuilders.rangeQuery("times").gte(i).lt(i+1)))
                    .addAggregation(ca)
                    .setSize(0)
                    .execute().actionGet();

            Cardinality agg=null;
            if(searchResponse.getAggregations()!=null){
                agg= searchResponse.getAggregations().get("distinct_ip"+i);
            }

            long ipcount=0;
            if(agg!=null){
                ipcount= agg.getValue();//0-1 1-2 2-3点
            }

            Map<String,Object> map = new HashMap<>();
            map.put("day",i+":00-"+i+":59");
            map.put("count",ipcount);
            list.add(map);
        }
        return  list;
    }


    /**
     * 新增独立访客 ——小时区间
     * @param curTime 搜索区间在当前小时以前
     * @param totalNoToday 不包含今天的历史uuid去重数据
     */
    public List<Map<String, Object>> getOvByTimeNode(String index, String type,String siteid,int curTime,long totalNoToday){
        SearchRequestBuilder searchBuilder = client.prepareSearch(index.split(",")).setIndicesOptions(IndicesOptions.lenientExpandOpen());
        List<Map<String, Object>> list=new ArrayList<Map<String, Object>>();
        long tempCount=totalNoToday;

        for (int i=0;i<=curTime;i++){
            //去重uuid
            AggregationBuilder ca= AggregationBuilders.cardinality("distinct_uuid"+i).field("uuid.keyword");

            /*
             *totalNoToday不包含今天的总量   历史+小于今天01:00(记录  下一之间段 减 上一时间段) 的- totalNoToday
             */
            String timenode=Tools.date2Str(new Date(),"yyyy-MM-dd");
            timenode+=" "+i+":59:59";
            long times=Tools.dateToStamp(timenode);

            SearchResponse searchResponse= searchBuilder.setQuery(QueryBuilders.boolQuery()
                    .filter(QueryBuilders.termQuery("siteid", siteid))
                    .filter(QueryBuilders.rangeQuery("time").lte(times)))
                    .addAggregation(ca)
                    .setSize(0)
                    .execute().actionGet();

            Cardinality agg=null;
            if(searchResponse.getAggregations()!=null){
                agg= searchResponse.getAggregations().get("distinct_uuid"+i);
            }

            long uuidcount=tempCount;
            if(agg!=null){
                uuidcount=agg.getValue();
            }

            //(历史+今天)去重 -历史
            long ovcount=uuidcount-tempCount;//
            if(ovcount<0){
                ovcount=0;
            }
            Map<String,Object> map = new HashMap<>();
            map.put("day",i+":00");
            map.put("count",ovcount);
            list.add(map);

            tempCount=uuidcount;//下一时间节点 减 上一时间节点总数
        }
        return  list;
    }


    //===============================广告位相关========================================

    /**
     * 查询广告位可见率top50
     * 1.根据host groupBy
     * 2.查询出的集合 根据 where host 查询总数 即为加载量
     * flag :true 升序 false 降序
     */
    public  List<Map<String,Object>> getAdvLoadTop(String index, String type,String siteid,boolean flag){

        List<Map<String,Object>> resultlist = new ArrayList<Map<String, Object>>();

        //初始化builder 聚合排序order(BucketOrder.count(flag))
        SearchRequestBuilder searchBuilder=client.prepareSearch(index.split(",")).setIndicesOptions(IndicesOptions.lenientExpandOpen());
        AggregationBuilder ca = AggregationBuilders.terms("host_agg").field("host.keyword").order(BucketOrder.count(flag)).size(50);

        SearchResponse response= searchBuilder.setQuery(QueryBuilders.boolQuery()
                .filter(QueryBuilders.termQuery("siteid", siteid))
                .filter(QueryBuilders.termQuery("isShow", "true")))
                .addAggregation(ca)
                .setSize(0)
                .execute().actionGet();

        Terms terms=null;
        if(response.getAggregations()!=null){
            terms = response.getAggregations().get("host_agg");
        }

        if(terms==null){
            return resultlist;
        }

        for (Terms.Bucket bucket : terms.getBuckets()) {
            Map<String,Object> map = new HashMap<>();
            map.put("host",bucket.getKey().toString());
            long showLoad=bucket.getDocCount();
            map.put("showLoad",showLoad);

            long allLoad=getLoadTotalCount(index,siteid,bucket.getKey().toString());
            //根据host 查询总数
            map.put("allLoad",allLoad);
            //比率
            String rate="0%";
            if(allLoad>0){
                rate=((showLoad/allLoad)*100)+"%";
            }
            map.put("rate",rate);
            resultlist.add(map);
        }
        return resultlist;
    }


    /**查询host 加载量*/
    public long getLoadTotalCount(String index, String siteid,String host) {
        SearchRequestBuilder searchBuilder = client.prepareSearch(index.split(",")).setIndicesOptions(IndicesOptions.lenientExpandOpen());
        SearchResponse searchResponse= searchBuilder.setQuery(QueryBuilders.boolQuery()
                .filter(QueryBuilders.termQuery("siteid", siteid))
                .filter(QueryBuilders.matchQuery("host", host)))
                .setSize(0)
                .execute().actionGet();
        long totalHits = searchResponse.getHits().totalHits;
        return totalHits;
    }


    //===========================浏览器相关==================================


    public long getBrowserCountByType(String index, String type,String siteid,String browser){
        SearchRequestBuilder searchBuilder = client.prepareSearch(index).setIndicesOptions(IndicesOptions.lenientExpandOpen());
        List<Map<String, Object>> list=new ArrayList<Map<String, Object>>();
        SearchResponse searchResponse = searchBuilder.setQuery(QueryBuilders.termQuery("siteid", siteid))
                .setPostFilter(QueryBuilders.matchQuery("browser",browser))
                .setSize(0)
                .execute().actionGet();
        long totalHits = searchResponse.getHits().totalHits;

        return  totalHits;
    }




    public  List<Map<String, Object>> getBrowserByTimeNode(String index, String type,String siteid,int curTime,String browser){
        SearchRequestBuilder searchBuilder = client.prepareSearch(index).setIndicesOptions(IndicesOptions.lenientExpandOpen());
        List<Map<String, Object>> list=new ArrayList<Map<String, Object>>();
        for (int i=0;i<=curTime;i++){
            SearchResponse searchResponse = searchBuilder.setQuery(QueryBuilders.boolQuery()
                    .filter(QueryBuilders.termQuery("siteid", siteid))
                    .filter(QueryBuilders.matchQuery("browser", browser))
                    .filter(QueryBuilders.rangeQuery("times").gte(i).lt(i+1)))
                    .setSize(0)
                    .execute().actionGet();
            long totalHits = searchResponse.getHits().totalHits;//0-1 1-2 2-3点
            Map<String,Object> map = new HashMap<>();
            map.put("day",i+":00-"+i+":59");
            map.put("count",totalHits);
            list.add(map);
        }
        return  list;
    }


    /**
     * 查询浏览器top10
     * browser  wechat chrome qq
     * flag :true 升序 false 降序
     */
    public  List<Map<String,Object>> getBrowserTop(String index, String type,String siteid,String browser,boolean flag){

        List<Map<String,Object>> resultlist = new ArrayList<Map<String, Object>>();

        //初始化builder 聚合排序order(BucketOrder.count(flag))
        SearchRequestBuilder searchBuilder=client.prepareSearch(index.split(",")).setIndicesOptions(IndicesOptions.lenientExpandOpen());
        AggregationBuilder ca = AggregationBuilders.terms("host1_agg").field("host.keyword").order(BucketOrder.count(flag)).size(10);

        SearchResponse response= searchBuilder.setQuery(QueryBuilders.boolQuery()
                .filter(QueryBuilders.termQuery("siteid", siteid))
                .filter(QueryBuilders.matchQuery("browser", browser)))
                .addAggregation(ca)
                .setSize(0)
                .execute().actionGet();

        Terms terms=null;
        if(response.getAggregations()!=null){
            terms = response.getAggregations().get("host1_agg");
        }

        if(terms==null){
            return resultlist;
        }

        for (Terms.Bucket bucket : terms.getBuckets()) {
            Map<String,Object> map = new HashMap<>();
            map.put("host",bucket.getKey().toString());
            map.put("count",bucket.getDocCount());
            resultlist.add(map);
        }
        return resultlist;
    }

    //===============================手机品牌相关===============================
    /**
     * 查询手机品牌top10
     */
    public  List<Map<String,Object>> getPhoneBrandTop(String index, String type,String siteid,boolean flag){

        List<Map<String,Object>> resultlist = new ArrayList<Map<String, Object>>();

        //初始化builder 聚合排序order(BucketOrder.count(flag))
        SearchRequestBuilder searchBuilder=client.prepareSearch(index.split(",")).setIndicesOptions(IndicesOptions.lenientExpandOpen());
        AggregationBuilder ca = AggregationBuilders.terms("device_agg").field("agent.device.keyword").order(BucketOrder.count(flag)).size(10);

        SearchResponse response= searchBuilder.setQuery(QueryBuilders.boolQuery()
                .filter(QueryBuilders.termQuery("siteid", siteid))
                .mustNot(QueryBuilders.matchQuery("agent.device","Other")))
                .addAggregation(ca)
                .setSize(0)
                .execute().actionGet();

        Terms terms=null;
        if(response.getAggregations()!=null){
            terms = response.getAggregations().get("device_agg");
        }

        if(terms==null){
            return resultlist;
        }

        for (Terms.Bucket bucket : terms.getBuckets()) {
            Map<String,Object> map = new HashMap<>();
            map.put("name",bucket.getKey().toString());
            map.put("value",bucket.getDocCount());
            resultlist.add(map);
        }
        return resultlist;
    }


    /**
     * 查找手机品牌与平台差异过大的
     * 1.获取平台的前三 比例
     * 2.查找所有的host
     * 3.每个host作为筛选条件查出bucket 与 前三的brandName匹配  然后算出比例
     */
    public  List<Map<String,Object>> getDifferenceTop(String index, String type,String siteid){
        List<Map<String,Object>> resultlist = new ArrayList<Map<String, Object>>();

        //获取平台总的品牌比例  例:iphone 0.45*100->45    最后拼个%就行
        SearchRequestBuilder searchBuilder=client.prepareSearch(index.split(",")).setIndicesOptions(IndicesOptions.lenientExpandOpen());
        AggregationBuilder ca = AggregationBuilders.terms("device_agg").field("agent.device.keyword").order(BucketOrder.count(false)).size(3);
        SearchResponse response= searchBuilder.setQuery(QueryBuilders.boolQuery()
                .filter(QueryBuilders.termQuery("siteid", siteid)))
                .addAggregation(ca)
                .setSize(0)
                .execute().actionGet();

        Terms terms=null;
        if(response.getAggregations()!=null){
            terms = response.getAggregations().get("device_agg");
        }
        if(terms==null){
            return resultlist;
        }
        long totalHits = response.getHits().totalHits;
        if(totalHits<=0){
            return resultlist;
        }
        BigDecimal total = new BigDecimal(totalHits);
        List<Map<String,Object>> totalList=new ArrayList<Map<String, Object>>();
        //平台总的 例:iphone 0.45
        for (Terms.Bucket bucket : terms.getBuckets()) {
            Map<String,Object> map = new HashMap<>();
            map.put("brand",bucket.getKey().toString());
            //算出总量的百分比
            BigDecimal rate = new BigDecimal(bucket.getDocCount());
            rate=rate.divide(total, 2, RoundingMode.HALF_UP);
            map.put("rate",rate);
            totalList.add(map);
        }
        if(totalList.size()<=0){
            return  resultlist;
        }

        //查询所有的host
        List<String> hostList=getAllHosts(index,type,siteid);
        if(hostList.size()<=0){
            return resultlist;
        }
        //把不同的host当作筛选条件 算出百分比
        try {
            Integer i=1;
            for (String s: hostList) {
                AggregationBuilder a1 = AggregationBuilders.terms("device_agg"+i).field("agent.device.keyword").order(BucketOrder.count(false));
                SearchResponse res1= searchBuilder.setQuery(QueryBuilders.boolQuery()
                        .filter(QueryBuilders.termQuery("siteid", siteid))
                        .filter(QueryBuilders.matchQuery("host", s)))
                        .addAggregation(a1)
                        .setSize(0)
                        .execute().actionGet();

                Terms t1 = response.getAggregations().get("device_agg"+i);
                BigDecimal lastRate=new BigDecimal(0);


                for (Terms.Bucket bucket : t1.getBuckets()) {
                    //算出该host比例
                    //循环3个品牌  直接算到量
                    for (Map m: totalList) {
                        String brand=m.get("brand").toString();
                        if(brand.equals(bucket.getKeyAsString())){
                            BigDecimal rate1 = new BigDecimal(bucket.getDocCount());
                            rate1=rate1.divide(total,2,RoundingMode.HALF_UP);
                            BigDecimal trate=new BigDecimal(Double.valueOf(m.get("rate").toString()));

                            lastRate=lastRate.add((trate.subtract(rate1)).pow(2));//总-某个站的  的^2
                        }
                    }

                }
                double lr=Math.sqrt(lastRate.doubleValue());
                lastRate=new BigDecimal(lr);
                lastRate=lastRate.setScale(2, BigDecimal.ROUND_HALF_UP);

                Map<String,Object> map = new HashMap<>();
                map.put("host",s);
                map.put("rate",lastRate);
                //根据s host筛选条件查询总数 浏览量
                long r=getViewsByHost(index,type,siteid,s);
                map.put("views",r);
                resultlist.add(map);
                i++;
            }
            //todo
            //得到的resultlist  筛选排序 10个


        }catch (Exception e){
            e.getStackTrace();
            return resultlist;
        }

        return resultlist;
    }




    //查询所有的host url
    private List<String> getAllHosts(String index, String type,String siteid){
        List<String> resultlist = new ArrayList<String>();
        //初始化builder 聚合排序order(BucketOrder.count(flag))
        SearchRequestBuilder searchBuilder=client.prepareSearch(index.split(",")).setIndicesOptions(IndicesOptions.lenientExpandOpen());
        AggregationBuilder ca = AggregationBuilders.terms("host_agg").field("host.keyword").order(BucketOrder.count(false));

        SearchResponse response= searchBuilder.setQuery(QueryBuilders.boolQuery()
                .filter(QueryBuilders.termQuery("siteid", siteid)))
                .addAggregation(ca)
                .setSize(0)
                .execute().actionGet();

        Terms terms=null;
        if(response.getAggregations()!=null){
            terms = response.getAggregations().get("host_agg");
        }

        if(terms==null){
            return resultlist;
        }

        for (Terms.Bucket bucket : terms.getBuckets()) {
            resultlist.add(bucket.getKey().toString());
        }
        return resultlist;
    }

//查询浏览量by 网站url



    private long getViewsByHost(String index, String type,String siteid,String host){
        long r=0;
        try {
            SearchRequestBuilder searchBuilder = client.prepareSearch(index).setIndicesOptions(IndicesOptions.lenientExpandOpen());
            List<Map<String, Object>> list=new ArrayList<Map<String, Object>>();
            SearchResponse searchResponse = searchBuilder.setQuery(QueryBuilders.termQuery("siteid", siteid))
                    .setPostFilter(QueryBuilders.matchQuery("host",host))
                    .setSize(0)
                    .execute().actionGet();
            r = searchResponse.getHits().totalHits;
        }catch (Exception e){
            e.getStackTrace();
            return r;
        }
        return r;
    }

    //=====================定时任务相关====================

    /**
     * 获取当天所有index
     */
    public List getAllIndices() {
        ActionFuture<IndicesStatsResponse> isr = client.admin().indices().stats(new IndicesStatsRequest().all());
        Set<String> set = isr.actionGet().getIndices().keySet();

        String today=Tools.date2Str(new Date(),"yyyyMMdd");

        List<String> list=new ArrayList<String>();
        for (String s: set) {
            if(s.indexOf("_")>0 &&s.indexOf(today)>0){
                list.add(s);
            }
        }
        return list;
    }

    /**
     * 获取当前索引下所有的siteId
     * @param index
     * @return
     */
    public List<String> getAllSiteIdByIndex(String index){
        List<String> resultlist = new ArrayList<String>();
        try {
            SearchRequestBuilder searchBuilder=client.prepareSearch(index);
            AggregationBuilder ca = AggregationBuilders.terms("siteid_agg").field("siteid.keyword");

            SearchResponse response= searchBuilder
                    .addAggregation(ca)
                    .setSize(0)
                    .execute().actionGet();
            Terms terms=response.getAggregations().get("siteid_agg");
            if(terms==null){
                return resultlist;
            }
            for (Terms.Bucket bucket : terms.getBuckets()) {
                resultlist.add(bucket.getKey().toString());
            }
        }catch (Exception e){
            e.getStackTrace();
        }
        return resultlist;
    }


    /**
     * 查询pv——>入库
     * 1.根据lmid siteid day time 如果不存在新增记录 存在 修改记录
     */
    public boolean getPvToSave(String index,String siteid,String today,int curTime){
        SearchRequestBuilder searchBuilder = client.prepareSearch(index);
        List<Map<String, Object>> list=new ArrayList<Map<String, Object>>();
        String lmid=index.split("_")[1];
        if(Tools.isEmpty(lmid)){
            return false;
        }

        SearchResponse searchResponse = searchBuilder.setQuery(QueryBuilders.boolQuery()
                .filter(QueryBuilders.termQuery("siteid", siteid))
                .filter(QueryBuilders.rangeQuery("times").gte(curTime).lt(curTime+1)))
                .setSize(0)
                .execute().actionGet();
        long totalHits = searchResponse.getHits().totalHits;//0 1 2 3点
        //新增入库
        //lmid (截取index) siteid:siteid day：today time:curtime
        //不存在新增，存在及修改
        Pv pv=new Pv();
        pv.setLmid(lmid);
        pv.setSiteid(siteid);
        pv.setDay(today);
        pv.setTime(String.valueOf(curTime));//0 1 2 3 4
        pv.setNum(String.valueOf(totalHits));
        //根据条件查询
        Pv pv2=pvMapper.getPvInfoByParam(pv);
        if(pv2!=null){
            //修改
            pv.setId(pv2.getId());
            pvMapper.updateByPrimaryKeySelective(pv);
        }else{
            //新增
            pv.setId(Tools.getUUID());
            pvMapper.insert(pv);
        }

        return  true;
    }

    public  boolean getUvToSave(String index, String siteid,String today,int curTime){
        try {
            SearchRequestBuilder searchBuilder = client.prepareSearch(index);
            List<Map<String, Object>> list=new ArrayList<Map<String, Object>>();
            String tempNum=Tools.getRandomNum(3);
            String lmid=index.split("_")[1];
            if(Tools.isEmpty(lmid)){
                return false;
            }
            //去重uuid
            AggregationBuilder ca= AggregationBuilders.cardinality("distinct_uuid"+tempNum).field("uuid.keyword");
            SearchResponse searchResponse= searchBuilder.setQuery(QueryBuilders.boolQuery()
                    .filter(QueryBuilders.termQuery("siteid", siteid))
                    .filter(QueryBuilders.rangeQuery("times").gte(curTime).lt(curTime+1)))
                    .addAggregation(ca)
                    .setSize(0)
                    .execute().actionGet();

            Cardinality agg=null;
            if(searchResponse.getAggregations()!=null){
                agg= searchResponse.getAggregations().get("distinct_uuid"+tempNum);
            }
            long uuidcount=0;
            if(agg!=null){
                uuidcount=agg.getValue();//0-1 1-2 2-3点
            }
            //新增入库
            //lmid (截取index) siteid:siteid day：today time:curtime
            //不存在新增，存在及修改
            Uv uv=new Uv();
            uv.setLmid(lmid);
            uv.setSiteid(siteid);
            uv.setDay(today);
            uv.setTime(String.valueOf(curTime));//0 1 2 3 4
            uv.setNum(String.valueOf(uuidcount));
            //根据条件查询
            Uv uv2=uvMapper.getUvInfoByParam(uv);
            if(uv2!=null){
                //修改
                uv.setId(uv2.getId());
                uvMapper.updateByPrimaryKeySelective(uv);
            }else{
                //新增
                uv.setId(Tools.getUUID());
                uvMapper.insert(uv);
            }
            return  true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    public  boolean getIpsToSave(String index, String siteid,String today,int curTime){
        try {
            SearchRequestBuilder searchBuilder = client.prepareSearch(index).setIndicesOptions(IndicesOptions.lenientExpandOpen());
            List<Map<String, Object>> list=new ArrayList<Map<String, Object>>();
            String tempNum=Tools.getRandomNum(3);
            String lmid=index.split("_")[1];
            if(Tools.isEmpty(lmid)){
                return false;
            }
            //去重uuid
            AggregationBuilder ca= AggregationBuilders.cardinality("distinct_ip"+tempNum).field("ip.keyword").precisionThreshold(40000);
            SearchResponse searchResponse= searchBuilder.setQuery(QueryBuilders.boolQuery()
                    .filter(QueryBuilders.termQuery("siteid", siteid))
                    .filter(QueryBuilders.rangeQuery("times").gte(curTime).lt(curTime+1)))
                    .addAggregation(ca)
                    .setSize(0)
                    .execute().actionGet();

            Cardinality agg=null;
            if(searchResponse.getAggregations()!=null){
                agg= searchResponse.getAggregations().get("distinct_ip"+tempNum);
            }
            long ipcount=0;
            if(agg!=null){
                ipcount=agg.getValue();//0-1 1-2 2-3点
            }
            //新增入库
            //lmid (截取index) siteid:siteid day：today time:curtime
            //不存在新增，存在及修改
            Ips uv=new Ips();
            uv.setLmid(lmid);
            uv.setSiteid(siteid);
            uv.setDay(today);
            uv.setTime(String.valueOf(curTime));//0 1 2 3 4
            uv.setNum(String.valueOf(ipcount));
            //根据条件查询
            Ips uv2=ipsMapper.getIpsInfoByParam(uv);
            if(uv2!=null){
                //修改
                uv.setId(uv2.getId());
                ipsMapper.updateByPrimaryKeySelective(uv);
            }else{
                //新增
                uv.setId(Tools.getUUID());
                ipsMapper.insert(uv);
            }
            return  true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 新增独立访客 ——小时区间
     * @param curTime 搜索区间在当前小时以前
     * @param totalNoToday 不包含今天的历史uuid去重数据
     */
    public boolean getNewUvToSave(String lmid,String index, String siteid,String today,int curTime,String allIndex,long totalNoToday){
        try {
            SearchRequestBuilder searchBuilder = client.prepareSearch(allIndex.split(",")).setIndicesOptions(IndicesOptions.lenientExpandOpen());
            List<Map<String, Object>> list=new ArrayList<Map<String, Object>>();
            String tempNum=Tools.getRandomNum(3);

            long tempCount=totalNoToday;
            //去重uuid
            AggregationBuilder ca= AggregationBuilders.cardinality("distinct_uuid"+tempNum).field("uuid.keyword");

            /*
             *totalNoToday不包含今天的总量   历史+小于今天01:00(记录  下一之间段 减 上一时间段) 的- totalNoToday
             */
            String timenode=Tools.date2Str(new Date(),"yyyy-MM-dd");
            timenode+=" "+curTime+":59:59";
            long times=Tools.dateToStamp(timenode);

            SearchResponse searchResponse= searchBuilder.setQuery(QueryBuilders.boolQuery()
                    .filter(QueryBuilders.termQuery("siteid", siteid))
                    .filter(QueryBuilders.rangeQuery("time").lte(times)))
                    .addAggregation(ca)
                    .setSize(0)
                    .execute().actionGet();

            Cardinality agg=null;
            if(searchResponse.getAggregations()!=null){
                agg= searchResponse.getAggregations().get("distinct_uuid"+tempNum);
            }

            long uuidcount=tempCount;
            if(agg!=null){
                uuidcount=agg.getValue();
            }

            //(历史+今天)去重 -历史
            long ovcount=uuidcount-tempCount;//
            if(ovcount<0){
                ovcount=0;
            }


            //新增入库
            //lmid (截取index) siteid:siteid day：today time:curtime
            //不存在新增，存在及修改
            Newuv uv=new Newuv();
            uv.setLmid(lmid);
            uv.setSiteid(siteid);
            uv.setDay(today);
            uv.setTime(String.valueOf(curTime));//0 1 2 3 4
            uv.setNum(String.valueOf(ovcount));
            //根据条件查询
            Newuv uv2=newuvMapper.getNewUvInfoByParam(uv);
            if(uv2!=null){
                //修改
                uv.setId(uv2.getId());
                newuvMapper.updateByPrimaryKeySelective(uv);
            }else{
                //新增
                uv.setId(Tools.getUUID());
                newuvMapper.insert(uv);
            }

            return  true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


//====================================推手作弊分析相关=============================================
    /**
     * 推手 cc2小说 3活动
     * @param index type 2 3
     * @return
     */
    public  List<Map<String, Object>> getCheatListByType(String index,String type){
        List<Map<String,Object>> resultlist = new ArrayList<Map<String, Object>>();
        List<Map<String,Object>> resultlist2 = new ArrayList<Map<String, Object>>();
        List<Map<String,Object>> alllist = new ArrayList<Map<String, Object>>();

        List<String> fingerList=new ArrayList<String>();

        SearchRequestBuilder searchBuilder=client.prepareSearch(index.split(",")).setIndicesOptions(IndicesOptions.lenientExpandOpen());

        //查询全部数量
        AggregationBuilder ca = AggregationBuilders.terms("sid_agg").field("sid.keyword").order(BucketOrder.count(false)).size(1000);


        SearchResponse response= searchBuilder.setQuery(QueryBuilders.boolQuery()
                .must(QueryBuilders.termQuery("type.keyword", type)))
                .addAggregation(ca)
                .setSize(0)
                .execute().actionGet();

        Terms terms=null;
        if(response.getAggregations()!=null){
            terms = response.getAggregations().get("sid_agg");
        }
        if(terms==null){
            return resultlist;
        }
        for (Terms.Bucket bucket : terms.getBuckets()) {
            Map<String,Object> map = new HashMap<>();
            map.put("sid",bucket.getKey().toString());
            map.put("allNum",bucket.getDocCount());
            alllist.add(map);
        }


        //查询问题数量——维度1：多uknown值
        AggregationBuilder ca2 = AggregationBuilders.terms("sid_agg2").field("sid.keyword").order(BucketOrder.count(false)).size(50);

        SearchResponse response2= searchBuilder.setQuery(QueryBuilders.boolQuery()
                .must(QueryBuilders.termQuery("type.keyword", type))
                .must(QueryBuilders.termQuery("renderer", "unknown"))
                .must(QueryBuilders.termQuery("vendor", "unknown"))
                .mustNot(QueryBuilders.termQuery("finger.keyword", "2a650bf9"))
                .mustNot(QueryBuilders.termQuery("finger.keyword", "e30f7650"))
                .should(QueryBuilders.termQuery("batteryCharging", "true"))
                .should(QueryBuilders.termQuery("batteryLevel", "1"))
                .should(QueryBuilders.termQuery("batteryCharging", "unknown"))
                .should(QueryBuilders.termQuery("batteryLevel", "unknown")))
                .addAggregation(ca2)
                .setSize(0)
                .execute().actionGet();

        Terms terms2=null;
        if(response2.getAggregations()!=null){
            terms2 = response2.getAggregations().get("sid_agg2");
        }
        if(terms2!=null){
            for (Terms.Bucket bucket : terms2.getBuckets()) {
                Map<String,Object> map = new HashMap<>();
                map.put("sid",bucket.getKey().toString());
                map.put("problemNum",bucket.getDocCount());
                map.put("info","硬件异常");
                if(bucket.getDocCount()>2 && !"".equals(bucket.getKey().toString())){
                    resultlist.add(map);
                }
            }
        }



        //查询问题数量——维度2：多重复finger不同ip
        AggregationBuilder ca3 = AggregationBuilders.terms("sid_agg3").field("finger.keyword").order(BucketOrder.count(false)).size(50);

        SearchResponse response3= searchBuilder.setQuery(QueryBuilders.boolQuery()
                .should(QueryBuilders.termQuery("_type", "doc"))
                .must(QueryBuilders.termQuery("type.keyword", type))
                .mustNot(QueryBuilders.termQuery("finger.keyword", "undefined"))
                .mustNot(QueryBuilders.termQuery("finger.keyword", "2a650bf9"))
                .mustNot(QueryBuilders.termQuery("finger.keyword", "e30f7650")))
                .addAggregation(ca3)
                .setSize(0)
                .execute().actionGet();


        Terms terms3=null;
        if(response3.getAggregations()!=null){
            terms3 = response3.getAggregations().get("sid_agg3");
            for (Terms.Bucket bucket : terms3.getBuckets()) {
                fingerList.add(bucket.getKey().toString());
            }
            //查出指纹相同列表 group by sid 循环条件fingerList
            for (String s:fingerList){

                AggregationBuilder ca4 = AggregationBuilders.terms("sid_agg"+s).field("sid.keyword").order(BucketOrder.count(false)).size(50);
                SearchResponse response4 = searchBuilder.setQuery(QueryBuilders.boolQuery()
                        .must(QueryBuilders.termQuery("type.keyword", type))
                        .filter(QueryBuilders.termQuery("finger", s)))
                        .addAggregation(ca4)
                        .setSize(0)
                        .execute().actionGet();

                Terms terms4=null;
                if(response4.getAggregations()!=null){
                    terms4 = response4.getAggregations().get("sid_agg"+s);
                }
                if(terms4==null){
                    return resultlist;
                }
                for (Terms.Bucket bucket : terms4.getBuckets()) {
                    Map<String,Object> map = new HashMap<>();
                    map.put("sid",bucket.getKey().toString());
                    map.put("problemNum",bucket.getDocCount());
                    map.put("info","指纹异常");
                    if(bucket.getDocCount()>5 && !"".equals(bucket.getKey().toString())){
                        resultlist2.add(map);
                    }


                }
            }
        }

        //合并两个维度list
        //resultlist.addAll(resultlist2);

        Map<String,Map<String,Object>> all = new HashMap<>();

        for (Map<String,Object> map1: resultlist){
            String key = map1.get("sid").toString();
            all.put(key,map1);
        }

        for (Map<String,Object> map2: resultlist2){
            String key = map2.get("sid").toString();
            if(all.containsKey(key)){
                Map<String, Object> maps = all.get(key);
                maps.put("info","硬件异常 | 指纹异常");
                all.put(key,maps);
            }else{
                map2.put("info","指纹异常");
                all.put(key,map2);
            }
        }

        Collection<Map<String, Object>> values = all.values();

        resultlist =new ArrayList<Map<String, Object>>();
        resultlist.addAll(values);



        //算比例
        for (Map<String,Object> map : resultlist){
            for (Map<String,Object> map2 : alllist){
                if(map2.get("sid").equals(map.get("sid"))){
                    map.put("allNum",map2.get("allNum"));

                    long r1=(long) map.get("problemNum");
                    long r2=(long) map.get("allNum");

                    double f=(double) r1/r2*100;

                    BigDecimal bg = new BigDecimal(f);
                    Double f1 = bg.setScale(2,RoundingMode.HALF_UP).doubleValue();



                    map.put("rate",f1);
                    map.put("colorrate",f1+"%");

                }
            }

        }
        Collections.sort(resultlist, new Comparator<Map<String, Object>>() {
            public int compare(Map<String, Object> o1, Map<String, Object> o2) {
                Double name1 = Double.valueOf(o1.get("rate").toString()) ;//name1是从你list里面拿出来的一个
                Double name2 = Double.valueOf(o2.get("rate").toString()) ; //name1是从你list里面拿出来的第二个name
                return name2.compareTo(name1);
            }
        });

        return resultlist;
    }


    /**
     * 推手 ff电影 作弊查询
     * @param index
     * @return
     */
    public  List<Map<String, Object>> getCheatList(String index){
        List<Map<String,Object>> resultlist = new ArrayList<Map<String, Object>>();
        List<Map<String,Object>> resultlist2 = new ArrayList<Map<String, Object>>();
        List<Map<String,Object>> alllist = new ArrayList<Map<String, Object>>();

        List<String> fingerList=new ArrayList<String>();

        SearchRequestBuilder searchBuilder=client.prepareSearch(index.split(",")).setIndicesOptions(IndicesOptions.lenientExpandOpen());

        //查询全部数量
        AggregationBuilder ca = AggregationBuilders.terms("sid_agg").field("sid.keyword").order(BucketOrder.count(false)).size(1000);


        SearchResponse response= searchBuilder
                .addAggregation(ca)
                .setSize(0)
                .execute().actionGet();

        Terms terms=null;
        if(response.getAggregations()!=null){
            terms = response.getAggregations().get("sid_agg");
        }
        if(terms==null){
            return resultlist;
        }
        for (Terms.Bucket bucket : terms.getBuckets()) {
            Map<String,Object> map = new HashMap<>();
            map.put("sid",bucket.getKey().toString());
            map.put("allNum",bucket.getDocCount());
            alllist.add(map);
        }


        //查询问题数量——维度1：多uknown值
        AggregationBuilder ca2 = AggregationBuilders.terms("sid_agg2").field("sid.keyword").order(BucketOrder.count(false)).size(50);

        SearchResponse response2= searchBuilder.setQuery(QueryBuilders.boolQuery()
                .must(QueryBuilders.termQuery("renderer", "unknown"))
                .must(QueryBuilders.termQuery("vendor", "unknown"))
                .mustNot(QueryBuilders.termQuery("finger.keyword", "2a650bf9"))
                .mustNot(QueryBuilders.termQuery("finger.keyword", "e30f7650"))
                .should(QueryBuilders.termQuery("batteryCharging", "true"))
                .should(QueryBuilders.termQuery("batteryLevel", "1"))
                .should(QueryBuilders.termQuery("batteryCharging", "unknown"))
                .should(QueryBuilders.termQuery("batteryLevel", "unknown")))
                .addAggregation(ca2)
                .setSize(0)
                .execute().actionGet();

        Terms terms2=null;
        if(response2.getAggregations()!=null){
            terms2 = response2.getAggregations().get("sid_agg2");
        }
        if(terms2!=null){
            for (Terms.Bucket bucket : terms2.getBuckets()) {
                Map<String,Object> map = new HashMap<>();
                map.put("sid",bucket.getKey().toString());
                map.put("problemNum",bucket.getDocCount());
                map.put("info","硬件异常");
                if(bucket.getDocCount()>2 && !"".equals(bucket.getKey().toString())){
                    resultlist.add(map);
                }
            }
        }



        //查询问题数量——维度2：多重复finger不同ip
        AggregationBuilder ca3 = AggregationBuilders.terms("sid_agg3").field("finger.keyword").order(BucketOrder.count(false)).size(50);

        SearchResponse response3= searchBuilder.setQuery(QueryBuilders.boolQuery()
                .should(QueryBuilders.termQuery("_type", "doc"))
                .mustNot(QueryBuilders.termQuery("finger.keyword", "undefined"))
                .mustNot(QueryBuilders.termQuery("finger.keyword", "2a650bf9"))
                .mustNot(QueryBuilders.termQuery("finger.keyword", "e30f7650")))
                .addAggregation(ca3)
                .setSize(0)
                .execute().actionGet();


        Terms terms3=null;
        if(response3.getAggregations()!=null){
            terms3 = response3.getAggregations().get("sid_agg3");
            for (Terms.Bucket bucket : terms3.getBuckets()) {
                fingerList.add(bucket.getKey().toString());
            }
            //查出指纹相同列表 group by sid 循环条件fingerList
            for (String s:fingerList){

                AggregationBuilder ca4 = AggregationBuilders.terms("sid_agg"+s).field("sid.keyword").order(BucketOrder.count(false)).size(50);
                SearchResponse response4 = searchBuilder.setQuery(QueryBuilders.boolQuery()
                        .filter(QueryBuilders.termQuery("finger", s)))
                        .addAggregation(ca4)
                        .setSize(0)
                        .execute().actionGet();

                Terms terms4=null;
                if(response4.getAggregations()!=null){
                    terms4 = response4.getAggregations().get("sid_agg"+s);
                }
                if(terms4==null){
                    return resultlist;
                }
                for (Terms.Bucket bucket : terms4.getBuckets()) {
                    Map<String,Object> map = new HashMap<>();
                    map.put("sid",bucket.getKey().toString());
                    map.put("problemNum",bucket.getDocCount());
                    map.put("info","指纹异常");
                    if(bucket.getDocCount()>5 && !"".equals(bucket.getKey().toString())){
                        resultlist2.add(map);
                    }


                }
            }
        }

        //合并两个维度list
        //resultlist.addAll(resultlist2);

        Map<String,Map<String,Object>> all = new HashMap<>();

        for (Map<String,Object> map1: resultlist){
            String key = map1.get("sid").toString();
            all.put(key,map1);
        }

        for (Map<String,Object> map2: resultlist2){
            String key = map2.get("sid").toString();
            if(all.containsKey(key)){
                Map<String, Object> maps = all.get(key);
                maps.put("info","硬件异常 | 指纹异常");
                all.put(key,maps);
            }else{
                map2.put("info","指纹异常");
                all.put(key,map2);
            }
        }

        Collection<Map<String, Object>> values = all.values();

        resultlist =new ArrayList<Map<String, Object>>();
        resultlist.addAll(values);



        //算比例
        for (Map<String,Object> map : resultlist){
            for (Map<String,Object> map2 : alllist){
                if(map2.get("sid").equals(map.get("sid"))){
                    map.put("allNum",map2.get("allNum"));

                    long r1=(long) map.get("problemNum");
                    long r2=(long) map.get("allNum");

                    double f=(double) r1/r2*100;

                    BigDecimal bg = new BigDecimal(f);
                    Double f1 = bg.setScale(2,RoundingMode.HALF_UP).doubleValue();



                    map.put("rate",f1);
                    map.put("colorrate",f1+"%");

                }
            }

        }
        Collections.sort(resultlist, new Comparator<Map<String, Object>>() {
            public int compare(Map<String, Object> o1, Map<String, Object> o2) {
                Double name1 = Double.valueOf(o1.get("rate").toString()) ;//name1是从你list里面拿出来的一个
                Double name2 = Double.valueOf(o2.get("rate").toString()) ; //name1是从你list里面拿出来的第二个name
                return name2.compareTo(name1);
            }
        });

        return resultlist;
    }




    //====================================推手作弊分析相关 广告平台=============================================

    public  List<Map<String, Object>> getCheatList3(String index){
        List<Map<String,Object>> resultlist =  new ArrayList();
        SearchRequestBuilder searchBuilder = client.prepareSearch(index.split(",")).setIndicesOptions(IndicesOptions.lenientExpandOpen());
        //查询全部数量
        AggregationBuilder ca = AggregationBuilders.terms("uid_agg").field("uid").order(BucketOrder.count(false)).size(2000);
        SearchResponse response= searchBuilder.addAggregation(ca).setSize(0).get();
        Terms terms = null;
        if(response.getAggregations() != null){
            terms = response.getAggregations().get("uid_agg");
        }
        if(terms==null){
            return resultlist;
        }
        //取出所有uid 分组聚合文档数量
        Map<String, Long> alllist = terms.getBuckets().parallelStream().collect(Collectors.toMap(x -> x.getKeyAsString(), x-> x.getDocCount()));

        //查询问题数量——维度1：多uknown值
        AggregationBuilder ca2 = AggregationBuilders.terms("uid_agg2").field("uid").order(BucketOrder.count(false)).size(50);
        SearchResponse response2= searchBuilder.setQuery(
                QueryBuilders.boolQuery()
                        .must(QueryBuilders.termQuery("renderer", "unknown"))
                        .must(QueryBuilders.termQuery("vendor", "unknown"))
                        .mustNot(QueryBuilders.termQuery("finger.keyword","2a650bf9"))
                        .mustNot(QueryBuilders.termQuery("finger.keyword", "e30f7650"))
                        .should(QueryBuilders.termQuery("batterycharging", "true"))
                        .should(QueryBuilders.termQuery("batterylevel", "1"))
                        .should(QueryBuilders.termQuery("batterycharging", "unknown"))
                        .should(QueryBuilders.termQuery("batterylevel", "unknown"))
        ).addAggregation(ca2).setSize(0).get();

        Terms terms2=null;
        if(response2.getAggregations()!=null){
            terms2 = response2.getAggregations().get("uid_agg2");
        }
        final Map<String, ConcurrentHashMap<String, Object>> termsCollect = new ConcurrentHashMap<>();

        //计算比例 函数
        RateCalculation rc = (x,y)->{
            double f=(double) x/y*100;
            BigDecimal bg = new BigDecimal(f);
            Double f1 = bg.setScale(2,RoundingMode.HALF_UP).doubleValue();
            return f1;
        };

        if(terms2!=null){
            //取出所有硬件异常uid
            termsCollect.putAll(terms2.getBuckets().parallelStream()
                    .filter(x -> x.getDocCount() > 2 && !"".equals(x.getKey().toString()))
                    .map(x -> {
                        String key = x.getKeyAsString();
                        //算比例
                        long docCount = x.getDocCount();
                        long allNum = alllist.get(key);
                        Double rate = rc.calc(docCount,allNum);

                        ConcurrentHashMap<String, Object> map = new ConcurrentHashMap<>(8);
                        map.put("uid", key);
                        map.put("problemNum", docCount);
                        map.put("allNum",allNum);
                        map.put("info", "硬件异常");
                        map.put("rate",rate);
                        map.put("colorrate",rate+"%");
                        return map;
                    }).collect(Collectors.toMap(x -> x.get("uid").toString(), v -> v)));
        }

        //查询问题数量——维度2：多重复finger不同ip
        //AggregationBuilder ca3 = AggregationBuilders.terms("sid_agg3").field("finger.keyword").order(BucketOrder.count(false)).size(50);
        AggregationBuilder ca3 =AggregationBuilders.terms("finger_agg").field("finger.keyword").size(100);

        SearchResponse response3= searchBuilder.setQuery(
                QueryBuilders.boolQuery()
                        .should(QueryBuilders.termQuery("_type", "doc"))
                        .mustNot(QueryBuilders.termQuery("finger.keyword",""))
                        .mustNot(QueryBuilders.termQuery("finger.keyword","2a650bf9"))
                        .mustNot(QueryBuilders.termQuery("finger.keyword", "e30f7650"))
        ).addAggregation(ca3).setSize(0).get();

        Terms terms3;
        //查出指纹相同列表 group by sid 循环条件fingerList
        if(response3.getAggregations()!=null){
            terms3 = response3.getAggregations().get("finger_agg");
            terms3.getBuckets().parallelStream().map(MultiBucketsAggregation.Bucket::getKeyAsString)
                    .forEach(s -> {
                        AggregationBuilder ca4 = AggregationBuilders.terms("uid_agg" + s).field("uid").order(BucketOrder.count(false)).size(1000);
                        SearchResponse response4 = client.prepareSearch(index.split(",")).setIndicesOptions(IndicesOptions.lenientExpandOpen())
                                .setQuery(
                                        QueryBuilders.boolQuery()
                                                .filter(QueryBuilders.termQuery("finger", s))
                                ).addAggregation(ca4).setSize(0).get();
                        Terms terms4 = null;
                        if (response4.getAggregations() != null) {
                            terms4 = response4.getAggregations().get("uid_agg" + s);
                        }
                        if (terms4 == null) {
                            return;
                        }
                        terms4.getBuckets().parallelStream()
                                .filter(y -> y.getDocCount() > 5 && !"".equals(y.getKey().toString()))
                                .forEach(z -> {
                                    String key = z.getKey().toString();
                                    if (termsCollect.containsKey(key)) {
                                        Map<String, Object> map = termsCollect.get(key);
                                        String info = map.get("info").toString();
                                        if(info.equals("指纹异常")){
                                            long docCount1 = z.getDocCount();
                                            long docCount2 = (long)map.get("problemNum");
                                            if(docCount1 > docCount2){
                                                //重新计算比例取最大比例
                                                long allNum = alllist.get(key);
                                                Double rate = rc.calc(docCount1,allNum);
                                                map.put("problemNum",docCount1);
                                                map.put("rate",rate);
                                                map.put("colorrate",rate+"%");
                                            }
                                        }else {
                                            map.put("info", "硬件异常 | 指纹异常");
                                        }
                                    } else {
                                        //算比例
                                        long docCount = z.getDocCount();
                                        long allNum = alllist.get(key);
                                        Double rate = rc.calc(docCount,allNum);

                                        ConcurrentHashMap<String, Object> map = new ConcurrentHashMap<>(8);
                                        map.put("uid", key);
                                        map.put("problemNum",docCount);
                                        map.put("info", "指纹异常");
                                        map.put("allNum",allNum);
                                        map.put("rate",rate);
                                        map.put("colorrate",rate+"%");
                                        termsCollect.put(key, map);
                                    }
                                });
                    });
        }
        //根据比例排序 比例相同按照文档总数排序
        resultlist = termsCollect.values().parallelStream().sorted((o1, o2) -> {
            Double name1 = Double.valueOf(o1.get("rate").toString()) ;//name1是从你list里面拿出来的一个
            Double name2 = Double.valueOf(o2.get("rate").toString()) ; //name1是从你list里面拿出来的第二个name
            int s1 = name2.compareTo(name1);
            if(0 == s1){
                Long num1 = (long)o1.get("allNum");
                Long num2 = (long)o2.get("allNum");
                return num2.compareTo(num1);
            }
            return s1;
        }).collect(Collectors.toList());
        return resultlist;
    }


    /**
     * cpa相关
     */
    public  List<Map<String, Object>> getCpaCheatList(String index){
        List<Map<String,Object>> resultlist = new ArrayList<Map<String, Object>>();
        List<Map<String,Object>> alllist = new ArrayList<Map<String, Object>>();

        List<String> regionList=new ArrayList<String>();

        SearchRequestBuilder searchBuilder=client.prepareSearch(index.split(",")).setIndicesOptions(IndicesOptions.lenientExpandOpen());

        //查询全部数量
        AggregationBuilder ca = AggregationBuilders.terms("cpasid_agg").field("sid").order(BucketOrder.count(false)).size(500);


        SearchResponse response= searchBuilder
                .addAggregation(ca)
                .setSize(0)
                .execute().actionGet();

        Terms terms=null;
        if(response.getAggregations()!=null){
            terms = response.getAggregations().get("cpasid_agg");
        }
        if(terms==null){
            return resultlist;
        }
        for (Terms.Bucket bucket : terms.getBuckets()) {
            Map<String,Object> map = new HashMap<>();
            map.put("sid",bucket.getKey().toString());
            map.put("allNum",bucket.getDocCount());
            alllist.add(map);
        }


        //查询问题数量——维度：ip reginId区域相同
        AggregationBuilder ca3 = AggregationBuilders.terms("cpasid_agg3").field("regionid").order(BucketOrder.count(false)).size(50);

        SearchResponse response3= searchBuilder.setQuery(QueryBuilders.boolQuery()
                .should(QueryBuilders.termQuery("_type", "doc")))
                .addAggregation(ca3)
                .setSize(0)
                .execute().actionGet();


        Terms terms3=null;
        if(response3.getAggregations()!=null){
            terms3 = response3.getAggregations().get("cpasid_agg3");
            for (Terms.Bucket bucket : terms3.getBuckets()) {
                regionList.add(bucket.getKey().toString());
            }
            //查出区域相同列表 group by sid 循环条件fingerList
            for (String s:regionList){

                AggregationBuilder ca4 = AggregationBuilders.terms("cpasid"+s).field("sid").order(BucketOrder.count(false)).size(50);
                SearchResponse response4 = searchBuilder.setQuery(QueryBuilders.boolQuery()
                        .filter(QueryBuilders.termQuery("regionid", s)))
                        .addAggregation(ca4)
                        .setSize(0)
                        .execute().actionGet();

                Terms terms4=null;
                if(response4.getAggregations()!=null){
                    terms4 = response4.getAggregations().get("cpasid"+s);
                }
                if(terms4==null){
                    return resultlist;
                }
                for (Terms.Bucket bucket : terms4.getBuckets()) {
                    Map<String,Object> map = new HashMap<>();
                    map.put("sid",bucket.getKey().toString());
                    map.put("problemNum",bucket.getDocCount());
                    map.put("info","区域异常");
                    if(bucket.getDocCount()>1 && !"".equals(bucket.getKey().toString())){
                        resultlist.add(map);
                    }


                }
            }
        }


        //算比例
        for (Map<String,Object> map : resultlist){
            for (Map<String,Object> map2 : alllist){
                if(map2.get("sid").equals(map.get("sid"))){
                    map.put("allNum",map2.get("allNum"));
                    long r1=(long) map.get("problemNum");
                    long r2=(long) map.get("allNum");
                    double f=(double) r1/r2*100;
                    BigDecimal bg = new BigDecimal(f);
                    Double f1 = bg.setScale(2,RoundingMode.HALF_UP).doubleValue();

                    map.put("rate",f1);
                    map.put("colorrate",f1+"%");

                }
            }

        }
        Collections.sort(resultlist, new Comparator<Map<String, Object>>() {
            public int compare(Map<String, Object> o1, Map<String, Object> o2) {
                Double name1 = Double.valueOf(o1.get("rate").toString()) ;//name1是从你list里面拿出来的一个
                Double name2 = Double.valueOf(o2.get("rate").toString()) ; //name1是从你list里面拿出来的第二个name
                return name2.compareTo(name1);
            }
        });

        return resultlist;
    }


}